home *** CD-ROM | disk | FTP | other *** search
/ EnigmA Amiga Run 1999 March / EnigmA AMIGA RUN 35 (1999)(G.R. Edizioni)(IT)[!][issue 1999-03].iso / earcd / grafica / amhelios / rad_eqn.cpp < prev    next >
C/C++ Source or Header  |  1999-01-01  |  9KB  |  339 lines

  1. ////////////////////////////////////////////////////////////
  2. //
  3. //  RAD_EQN.CPP - Radiosity Equation Solver Base Class
  4. //
  5. //  Version:    1.03A
  6. //
  7. //  History:    94/08/23 - Version 1.00A release.
  8. //              94/09/24 - Added GetElapsedTime function.
  9. //              94/11/26 - Added AddEmittance and Shade
  10. //                         functions.
  11. //                       - Modified CalcAmbient function.
  12. //              94/12/16 - Version 1.01A release.
  13. //              95/02/05 - Version 1.02A release.
  14. //              95/07/21 - Version 1.02B release.
  15. //              96/02/14 - Version 1.02C release.
  16. //              96/04/01 - Version 1.03A release.
  17. //
  18. //  Compilers:  Microsoft Visual C/C++ Professional V1.5
  19. //              Borland C++ Version 4.5
  20. //
  21. //  Author:     Ian Ashdown, P.Eng.
  22. //              byHeart Software Limited
  23. //              620 Ballantree Road
  24. //              West Vancouver, B.C.
  25. //              Canada V7S 1W3
  26. //              Tel. (604) 922-6148
  27. //              Fax. (604) 987-7621
  28. //
  29. //  Copyright 1994-1996 byHeart Software Limited
  30. //
  31. //  The following source code has been derived from:
  32. //
  33. //    Ashdown, I. 1994. Radiosity: A Programmer's
  34. //    Perspective. New York, NY: John Wiley & Sons.
  35. //
  36. //  It may be freely copied, redistributed, and/or modified
  37. //  for personal use ONLY, as long as the copyright notice
  38. //  is included with all source code files.
  39. //
  40. ////////////////////////////////////////////////////////////
  41.  
  42. #include "rad_eqn.h"
  43.  
  44. // Initialize patch and element exitances
  45. void RadEqnSolve::InitExitance()
  46. {
  47.   int i;                // Loop index
  48.   int num_vert;         // Number of element vertices
  49.   Instance *pinst;      // Instance pointer
  50.   Element3 *pelem;      // Element pointer
  51.   Patch3 *ppatch;       // Patch pointer
  52.   Surface3 *psurf;      // Surface pointer
  53.   Spectra emit;         // Surface emittance
  54.   Vertex3 *pvert;       // Vertex pointer
  55.  
  56.   total_flux = 0.0;
  57.  
  58.   // Walk the instance list
  59.   pinst = penv->GetInstPtr();
  60.   while (pinst != NULL)
  61.   {
  62.     // Walk the surface list
  63.     psurf = pinst->GetSurfPtr();
  64.     while (psurf != NULL)
  65.     {
  66.       // Get surface emittance
  67.       emit = psurf->GetEmittance();
  68.  
  69.       // Walk the patch list
  70.       ppatch = psurf->GetPatchPtr();
  71.       while (ppatch != NULL)
  72.       {
  73.         // Set patch unsent exitance
  74.         ppatch->SetExitance(emit);
  75.  
  76.         // Update total environment flux
  77.         total_flux += ppatch->GetUnsentFlux();
  78.  
  79.         // Walk the element list
  80.         pelem = ppatch->GetElementPtr();
  81.         while (pelem != NULL)
  82.         {
  83.           // Initialize element exitance
  84.           pelem->GetExitance().Reset();
  85.  
  86.           num_vert = pelem->GetNumVert();
  87.           for (i = 0; i < num_vert; i++)
  88.           {
  89.             // Get element vertex pointer
  90.             pvert = pelem->GetVertexPtr(i);
  91.  
  92.             // Initialize vertex exitance
  93.             pvert->GetExitance().Reset();
  94.           }
  95.           pelem = pelem->GetNext();
  96.         }
  97.         ppatch = ppatch->GetNext();
  98.       }
  99.       psurf = psurf->GetNext();
  100.     }
  101.     pinst = pinst->GetNext();
  102.   }
  103. }
  104.  
  105. // Update unsent flux statistics
  106. void RadEqnSolve::UpdateUnsentStats()
  107. {
  108.   double curr_unsent;   // Current unsent flux
  109.   double max_unsent;    // Maximum unsent flux
  110.   Instance *pinst;      // Instance pointer
  111.   Patch3 *ppatch;       // Patch pointer
  112.   Surface3 *psurf;      // Surface pointer
  113.  
  114.   // Initialize unsent flux values
  115.   total_unsent = 0.0;
  116.   max_unsent = 0.0;
  117.  
  118.   // Walk the instance list
  119.   pinst = penv->GetInstPtr();
  120.   while (pinst != NULL)
  121.   {
  122.     // Walk the surface list
  123.     psurf = pinst->GetSurfPtr();
  124.     while (psurf != NULL)
  125.     {
  126.       // Walk the patch list
  127.       ppatch = psurf->GetPatchPtr();
  128.       while (ppatch != NULL)
  129.       {
  130.         // Get current unsent flux value
  131.         curr_unsent = ppatch->GetUnsentFlux();
  132.  
  133.         // Update total unsent flux
  134.         total_unsent += curr_unsent;
  135.  
  136.         // Update maximum unsent flux and patch pointer
  137.         if (curr_unsent > max_unsent)
  138.         {
  139.           max_unsent = curr_unsent;
  140.           pmax = ppatch;
  141.         }
  142.         ppatch = ppatch->GetNext();
  143.       }
  144.       psurf = psurf->GetNext();
  145.     }
  146.     pinst = pinst->GetNext();
  147.   }
  148.  
  149.   // Update convergence value
  150.   if (total_flux > MIN_VALUE)
  151.     convergence = fabs(total_unsent) / total_flux;
  152.   else
  153.     convergence = 0.0;
  154. }
  155.  
  156. // Calculate interreflection factors
  157. void RadEqnSolve::CalcInterReflect()
  158. {
  159.   Instance *pinst;  // Instance pointer
  160.   Patch3 *ppatch;   // Patch pointer
  161.   Spectra sr;       // Surface reflectance
  162.   Spectra sum;      // Sum areas times reflectances
  163.   Surface3 *psurf;  // Surface pointer
  164.  
  165.   irf.Reset();
  166.   sum.Reset();
  167.   total_area = 0.0;
  168.  
  169.   // Walk the instance list
  170.   pinst = penv->GetInstPtr();
  171.   while (pinst != NULL)
  172.   {
  173.     // Walk the surface list
  174.     psurf = pinst->GetSurfPtr();
  175.     while (psurf != NULL)
  176.     {
  177.       // Walk the patch list
  178.       ppatch = psurf->GetPatchPtr();
  179.       while (ppatch != NULL)
  180.       {
  181.         // Update sum of patch areas times reflectances
  182.         sr = ppatch->GetParentPtr()->GetReflectance();
  183.         sr.Scale(ppatch->GetArea());
  184.         sum.Add(sr);
  185.  
  186.         // Update sum of patch areas
  187.         total_area += ppatch->GetArea();
  188.  
  189.         ppatch = ppatch->GetNext();
  190.       }
  191.       psurf = psurf->GetNext();
  192.     }
  193.     pinst = pinst->GetNext();
  194.   }
  195.  
  196.   // Calculate area-weighted average reflectance
  197.   sum.Scale(1.0 / total_area);
  198.  
  199.   // Calculate interreflection factors
  200.   irf.SetRedBand((float) 1.0 / ((float) 1.0 -
  201.       sum.GetRedBand()));
  202.   irf.SetGreenBand((float) 1.0 / ((float) 1.0 -
  203.       sum.GetGreenBand()));
  204.   irf.SetBlueBand((float) 1.0 / ((float) 1.0 -
  205.       sum.GetBlueBand()));
  206. }
  207.  
  208. // Calculate ambient exitance
  209. void RadEqnSolve::CalcAmbient()
  210. {
  211.   Instance *pinst;  // Instance pointer
  212.   Patch3 *ppatch;   // Patch pointer
  213.   Spectra sum;      // Sum areas times unsent exitances
  214.   Spectra unsent;   // Patch unsent exitance
  215.   Surface3 *psurf;  // Surface pointer
  216.  
  217.   sum.Reset();
  218.  
  219.   // Walk the instance list
  220.   pinst = penv->GetInstPtr();
  221.   while (pinst != NULL)
  222.   {
  223.     // Walk the surface list
  224.     psurf = pinst->GetSurfPtr();
  225.     while (psurf != NULL)
  226.     {
  227.       // Walk the patch list
  228.       ppatch = psurf->GetPatchPtr();
  229.       while (ppatch != NULL)
  230.       {
  231.         // Update sum of unsent exitances times areas
  232.         unsent = ppatch->GetExitance();
  233.         unsent.Scale(ppatch->GetArea());
  234.         sum.Add(unsent);
  235.  
  236.         ppatch = ppatch->GetNext();
  237.       }
  238.       psurf = psurf->GetNext();
  239.     }
  240.     pinst = pinst->GetNext();
  241.   }
  242.  
  243.   // Calculate area-weighted average unsent exitance
  244.   sum.Scale(1.0 / total_area);
  245.  
  246.   // Calculate ambient exitance
  247.   ambient = Mult(irf, sum);
  248. }
  249.  
  250. // Get elapsed calculation time
  251. char *RadEqnSolve::GetElapsedTime()
  252. {
  253.   unsigned long elapsed;        // Elapsed time in seconds
  254.   unsigned long hrs;            // Hours
  255.   unsigned long min;            // Minutes
  256.   unsigned long sec;            // Seconds
  257.  
  258.   // Get elapsed calculation time
  259.   elapsed = (unsigned long) GetElapsed() / CLOCKS_PER_SEC;
  260.  
  261.   hrs = elapsed / (60L * 60L);
  262.   min = (elapsed / 60L) % 60L;
  263.   sec = elapsed % 60L;
  264.  
  265.   // Format elapsed calculation time string
  266.   sprintf(timebuff, "%lu:%02lu:%02lu", hrs, min, sec);
  267.  
  268.   return timebuff;
  269. }
  270.  
  271. // Added surface emittance and determine maximum reflected
  272. // color band value
  273. void RadEqnSolve::AddEmittance()
  274. {
  275.   double cmax;          // Current color band value
  276.   double rmax = 0.0;    // Maximum color band value
  277.   Instance *pinst;      // Instance pointer
  278.   Spectra emit;         // Surface emittance
  279.   Vertex3 *pvert;       // Vertex pointer
  280.  
  281.   // Walk the instance list
  282.   pinst = penv->GetInstPtr();
  283.   while (pinst != NULL)
  284.   {
  285.     // Walk the vertex list
  286.     pvert = pinst->GetVertPtr();
  287.     while (pvert != NULL)
  288.     {
  289.       // Find maximum reflected color band value
  290.       if ((cmax = pvert->GetExitance().GetMaxColor()) >
  291.           rmax)
  292.         rmax = cmax;
  293.  
  294.       // Get parent surface emittance
  295.       emit = pvert->GetElemListPtr()->GetElemPtr()->
  296.           GetParentPtr()->GetParentPtr()->GetEmittance();
  297.  
  298.       // Add surface initial exitance to reflected vertex
  299.       // exitance
  300.       pvert->GetExitance().Add(emit);
  301.  
  302.       pvert = pvert->GetNext();
  303.     }
  304.     pinst = pinst->GetNext();
  305.   }
  306.  
  307.   // Set maximum reflected color band value
  308.   penv->SetMaxReflect(rmax);
  309. }
  310.  
  311. // Shade vertex exitances
  312. void RadEqnSolve::Shade( Environ *penv )
  313. {
  314.   Instance *pinst;
  315.   Vertex3 *pvert;
  316.  
  317.   // Walk the instance list
  318.   pinst = penv->GetInstPtr();
  319.   while (pinst != NULL)
  320.   {
  321.     // Walk the vertex list
  322.     pvert = pinst->GetVertPtr();
  323.     while (pvert != NULL)
  324.     {
  325.       // Set vertex exitance to parent surface reflectance
  326.       pvert->SetExitance(pvert->GetElemListPtr()->
  327.           GetElemPtr()->GetParentPtr()->GetParentPtr()->
  328.           GetReflectance());
  329.  
  330.       pvert = pvert->GetNext();
  331.     }
  332.     pinst = pinst->GetNext();
  333.   }
  334.  
  335.   // Set maximum reflected color band value
  336.   penv->SetMaxReflect(1.0);
  337. }
  338.  
  339.